package com.cskaoyan.javase.oop2._1extends._7fieldhidden;

/**
 * @description: 属性的隐藏
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 父子类中能否具有同名成员? 是可以的
 * 那么创建子类对象,用子类引用接收,然后用对象名点访问该同名成员,结果是什么呢?
 * 我们发现结果是子类中同名成员变量,那么在这个过程中,父类的同名成员去哪了,
 *      是被覆盖掉了?还是由于某种访问机制被隐藏起来了?
 * 通过访问同名成员的父类的get方法,发现该父类成员仍然存在,不是被覆盖掉了,仍然能够使用,说明它是被隐藏了
 *
 * 那么到底是什么机制决定它被隐藏了呢?
 * 我们要研究对象名点访问成员变量的访问机制,分成两个部分:
 *      1. 研究对象名点访问成员变量的访问范围
 *      2. 研究对象名点访问成员变量的访问结果
 * 在继承中,存在父子类时,创建对象的方式有三种:
 *      1.创建父类对象,用父类引用接收
 *      2.创建子类对象,用子类引用接收
 *      3.创建子类对象,用父类引用接收
 *
 * 接下来分三种情况讨论,
 * 首先是对象名点访问成员变量的访问范围:
 *      1.创建父类对象,用父类引用接收
 *          访问的范围在父类的范围(只有父类中存在的才能访问)
 *      2.创建子类对象,用子类引用接收
 *          访问的范围是父类+子类(自身的能够直接访问,父类的是继承过来的)
 *      3.创建子类对象,用父类引用接收
 *          访问的范围是父类的范围(只有父类中存在的才能访问)
 *      综上,对象名点成员变量,它的访问范围是由引用的数据类型来决定的,如果引用是父类类型,那么它的访问范围只有父类
 *          而如果引用是子类类型,那么它的访问范围是子类 + 父类
 *
 *      在Java当中,对象名点访问成员变量的范围是编译器决定的,编译在检索成员变量的存在以下检索机制:
 *          引用数据类型只能通过引用间接访问对象,而引用的声明就是为了告诉编译器引用的数据类型
 *          a.首先编译器会从引用的数据类型的类中去查找该成员变量,如果找到了,就直接认为它可以访问
 *              相反如果没有找到,那么就去父类中找
 *          b.最终找到Object类,如果Object类当中都没有该成员变量
 *              那就会编译报错
 *      在Java中,子类是知道自己有父类的(儿子知道爸爸存在),反之父类不知道自己有子类(爸爸不知道自己还有儿子)
 *
 *
 * 对象名点访问成员变量的访问结果:
 *      1.创建父类对象,用父类引用接收
 *          结果是父类中的结果
 *      2.创建子类对象,用子类引用接收
 *          结果是子类中的结果
 *      3.创建子类对象,用父类引用接收
 *          结果是父类中的结果
 *
 * 综合对象名点访问成员变量的范围和结果：
 *      都是根据引用的数据类型来决定的，无需考虑对象
 *
 * 注意事项：
 *      1.父子类中的同名成员变量它们各自有存储的区域，父类的同名成员变量被子类同名成员变量隐藏了
 *          但是我们仍然可以通过父类中的get方法，或者通过super.去访问到父类中同名成员变量
 *          需要注意的是： 它们都受访问权限限制
 *      2.静态成员变量在父子类中也存在同名的情况，但是它们不是覆盖也不是隐藏，而是互相独立的两个静态成员变量
 *
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        Son s = new Son();
        System.out.println(s.a); //100
        System.out.println(s.getA());
        s.getFatherA();

        /*Father f = new Father();
        System.out.println(f.a);
        //f.b;
        Son s = new Son();
        System.out.println(s.a);
        Father fs = new Son();
        System.out.println(fs.a);
        //fs.sonA;*/
    }
}

class Father {
    int a = 10;
    int fatherA = 20;

    //提供一个a的get方法
    public int getA() {
        return a;
    }
}

class Son extends Father {
    int a = 100;
    int sonA = 200;

    public void getFatherA(){
        System.out.println(super.a);
    }
}
